import axios from 'axios'
import {ElMessage, ElLoading} from 'element-plus'
import {safeNavigate} from './router'
import {v4 as uuidv4} from 'uuid'
import router from '@/router'
import {getCurrentLanguage} from "./i18n";

// 检查当前环境
const isDev = typeof import.meta !== 'undefined'
    ? import.meta.env && import.meta.env.MODE === 'development'
    : window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1';

// 创建一个Axios实例
const request = axios.create({
    baseURL: '', // 移除默认的/api前缀
    timeout: 600000, // 请求超时时间(毫秒)，增加到10分钟以支持大数据量导出
})

// 添加重试机制
request.interceptors.response.use(undefined, async (err) => {
    const config = err.config;

    // 记录详细的错误信息
    const requestId = config ? config.requestId : '未知';
    const requestUrl = config ? config.url : '未知URL';
    // console.error(`[请求失败-${requestId}] URL: ${requestUrl}, 错误: ${err.message}`);

    // 如果是401或403错误，不进行重试，直接处理认证错误
    if (err.response && (err.response.status === 401 || err.response.status === 403)) {
        // console.warn(`[认证错误-${requestId}] 状态码: ${err.response.status}, 不进行重试`);
        handleAuthError(requestId, err.response.status, config);
        return Promise.reject(err);
    }

    // 如果配置了重试，并且不是取消请求，那么就重试
    if (config && config.retry && !axios.isCancel(err)) {

        // 确定哪些状态码可以重试
        const canRetry = !err.response ||
            [500, 502, 503, 504, 507, 508, 429].includes(err.response.status);

        if (canRetry) {
            // 设置重试次数
            config.__retryCount = config.__retryCount || 0;

            // 如果当前重试次数不超过设定值，就重试
            if (config.__retryCount < config.retry) {
                config.__retryCount += 1;
                // 添加重试标记到请求头
                config.headers = config.headers || {};
                config.headers['X-Retry-Count'] = config.__retryCount;

                // 延时处理
                await new Promise(resolve => setTimeout(resolve, config.retryDelay || 1000));

                // 重新发送请求
                return request(config);
            } else {
                // console.warn(`[重试失败-${requestId}] 已达到最大重试次数(${config.retry})，放弃重试`);
            }
        } else {
            // console.warn(`[跳过重试-${requestId}] 状态码 ${err.response?.status} 不适合重试`);
        }
    }

    return Promise.reject(err);
});

// 请求计数器，用于调试
let requestCounter = 0;

/**
 * 安全地解码JWT负载部分
 * @param {string} token JWT令牌
 * @returns {object|null} 解码后的负载对象，如果解码失败则返回null
 */
function safeDecodeJwtPayload(token) {
    if (!token || typeof token !== 'string') {
        // console.warn('无效的JWT令牌');
        return null;
    }

    // 检查令牌格式
    const tokenParts = token.split('.');
    if (tokenParts.length !== 3) {
        // console.warn('JWT令牌格式不正确');
        return null;
    }

    try {
        // 获取并标准化base64负载
        const base64Payload = tokenParts[1];
        const normalizedBase64 = base64Payload.replace(/-/g, '+').replace(/_/g, '/');

        // 尝试多种解码方法，以处理可能的特殊字符
        let decodedPayload;

        try {
            // 方法1: 标准base64解码
            decodedPayload = atob(normalizedBase64);
        } catch (error) {
            // console.warn(`标准JWT解码失败: ${error.message}，尝试安全解码方法`);

            try {
                // 方法2: 使用decodeURIComponent安全解码
                // 将每个字符转为URL编码格式
                const encodedStr = Array.from(normalizedBase64).map(char => {
                    return '%' + char.charCodeAt(0).toString(16).padStart(2, '0');
                }).join('');

                try {
                    decodedPayload = decodeURIComponent(encodedStr);
                } catch (decodeError) {
                    // console.warn(`URL解码失败: ${decodeError.message}，使用原始字符串`);
                    // 方法3: 如果解码失败，尝试直接使用原始数据
                    decodedPayload = normalizedBase64;
                }
            } catch (e) {
                // console.error(`JWT安全解码完全失败: ${e.message}`);
                return null;
            }
        }

        // 解析JSON
        if (decodedPayload) {
            try {
                return JSON.parse(decodedPayload);
            } catch (jsonError) {
                // console.error(`JWT内容不是有效的JSON: ${jsonError.message}`);
                return null;
            }
        }
    } catch (error) {
        // console.error(`JWT解析过程出错: ${error.message}`);
    }

    return null;
}

// request拦截器
request.interceptors.request.use(
    config => {
        // 生成请求唯一ID，用于调试跟踪
        const requestId = uuidv4().substring(0, 8);
        config.requestId = requestId; // 将ID附加到配置中，便于响应拦截器使用

        const method = config.method ? config.method.toUpperCase() : 'GET';

        // 确保请求头正确
        config.headers = config.headers || {};

        // 统一从localStorage获取token
        const token = localStorage.getItem('token');
        // 检查请求是否需要认证
        const isAuthRequest = config.url.includes('/saas/auth/login') ||
            config.url.includes('/saas/auth/register') ||
            config.url.includes('/saas/auth/sms-code') ||
            config.url.includes('/saas/auth/sms/login') ||
            config.url.includes('/terms-of-service') ||
            config.url.includes('/privacy-policy') ||
            config._skipAuthRedirect === true;

        const isPublicApi = isAuthRequest ||
            config.url.includes('/public') ||
            config.meta?.isPublic;

        if (token && token.trim() !== '') {
            // 简单检查token格式是否正确
            if (token.split('.').length !== 3) {
                // console.warn(`[${requestId}] Token格式不正确，可能已过期`);

                if (!isPublicApi && !config.meta?.skipAuthRedirect) {
                    // 清除无效token
                    localStorage.removeItem('token');
                    localStorage.removeItem('username');
                    localStorage.removeItem('userId');
                    localStorage.removeItem('userInfo');
                    localStorage.removeItem('isFirstLogin');

                    // 保存当前路径
                    const currentPath = window.location.hash.substring(1) || '/';
                    localStorage.setItem('redirectPath', currentPath);

                    // 显示错误消息并跳转到登录页
                    if (getCurrentLanguage() === 'zh') {
                        ElMessage.warning('登录已过期，请重新登录');
                    } else {
                        ElMessage.warning('Session expired, please log in again');
                    }

                    // 使用setTimeout防止在请求拦截器中立即跳转引起的问题
                    setTimeout(() => {
                        router.push('/login');
                    }, 100);

                    // 取消请求
                    if (getCurrentLanguage() === 'zh') {
                        return Promise.reject(new axios.Cancel('登录已过期'));
                    } else {
                        return Promise.reject(new axios.Cancel('Session expired'));
                    }
                }
            } else {
                // 统一使用Authorization Bearer格式
                config.headers['Authorization'] = `Bearer ${token}`;
            }
        } else {
            if (!isPublicApi) {
                // console.warn(`[${requestId}] 未找到有效token，可能需要重新登录`);

                // 如果不是公开API，且没有token，则需要重定向到登录页
                if (!config.meta?.skipAuthRedirect && !config._skipAuthRedirect) {
                    // 保存当前路径
                    const currentPath = window.location.hash.substring(1) || '/';
                    localStorage.setItem('redirectPath', currentPath);

                    // 显示错误消息并跳转到登录页
                    if (getCurrentLanguage() === 'zh') {
                        ElMessage.warning('请先登录后再访问');
                    } else {
                        ElMessage.warning('Please log in first');
                    }

                    // 使用setTimeout防止在请求拦截器中立即跳转引起的问题
                    setTimeout(() => {
                        router.push('/login');
                    }, 100);

                    // 取消请求
                    if (getCurrentLanguage() === 'zh') {
                        return Promise.reject(new axios.Cancel('请先登录'));
                    } else {
                        return Promise.reject(new axios.Cancel('Please log in'));
                    }
                }
            } else {
                // console.log(`[${requestId}] 公开API请求，不需要token`);
            }
        }

        // 设置Content-Type
        if (!config.headers['Content-Type'] && method !== 'GET') {
            if (config.data instanceof FormData) {
                config.headers['Content-Type'] = 'multipart/form-data';
            } else if (config.data instanceof URLSearchParams) {
                config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
            } else {
                config.headers['Content-Type'] = 'application/json';
            }
        }

        // 确保基本URL正确
        if (config.url && config.url.startsWith('/')) {
            // 如果URL以/api/saas/开头，则不添加/api前缀
            if (config.url.startsWith('/api/saas/')) {
                // 保持原样，不添加前缀
                // console.log(`[${requestId}] 保持api/saas路径: ${config.url}`);
            } else if (config.url.startsWith('/api/')) {
                // 如果已经有/api前缀，保持原样
                // console.log(`[${requestId}] 保持api路径: ${config.url}`);
            } else {
                // 其他URL，如果不是以/api/开头，添加/api前缀
                config.url = '/api' + config.url;
            }
        }

        return config;
    },
    error => {
        // console.error('请求拦截器错误:', error);
        return Promise.reject(error);
    }
);

// 处理认证错误的函数
const handleAuthError = (requestId, status, config) => {
    // 检查是否是访问企业库的请求，如果是则不清除token也不跳转
    if (config && config.url && config.url.includes('/enterprises')) {
        return;
    }

    // 清除所有登录相关信息
    localStorage.removeItem('token');
    localStorage.removeItem('username');
    localStorage.removeItem('userId');
    localStorage.removeItem('userInfo');
    localStorage.removeItem('isFirstLogin');
    // 检查当前路径
    const currentRoute = router.currentRoute.value;
    if (currentRoute.path !== '/login') {
        // 保存当前路径用于登录后重定向
        localStorage.setItem('redirectPath', currentRoute.fullPath);
        // 显示错误消息
        try {
            if (getCurrentLanguage() === 'zh') {
                ElMessage.error(status === 401 ? '登录已过期，请重新登录' : '您没有权限访问该资源');
            } else {
                ElMessage.error(status === 401 ? 'Session expired, please log in again' : 'You do not have permission to access this resource');
            }
        } catch (e) {
            // console.error(`[消息显示错误-${requestId}]`, e);
        }

        router.push('/login');
    } else {
        // console.log(`[跳过跳转-${requestId}] 当前已在登录页，不再跳转`);
    }
};

// response拦截器
request.interceptors.response.use(
    /**
     * 处理响应数据
     */
    response => {
        const requestId = response.config.requestId || '未知';
        const method = response.config.method ? response.config.method.toUpperCase() : 'GET';
        const url = response.config.url || '未知URL';

        // 如果请求配置了responseType为blob并且被标记为导出请求，直接返回整个响应对象
        if (response.config.responseType === 'blob' && response.config.meta && response.config.meta.isExport) {
            // console.debug(`[${requestId}] 检测到文件导出请求，返回原始响应`);

            // 检查Content-Type是否为Excel或是错误JSON
            const contentType = response.headers['content-type'];
            if (contentType && contentType.includes('json') && response.data instanceof Blob) {
                // 可能是错误JSON包装成了Blob，我们需要解析它
                // console.warn(`[${requestId}] 导出请求返回了JSON而非Excel，尝试解析`);
                // 由于这里无法直接解析Blob，我们只能返回响应，让业务代码处理
            }

            return response;
        }

        // 处理大整数精度问题，将大整数转换为字符串
        const processLargeIntegers = (obj) => {
            if (!obj || typeof obj !== 'object') return obj;

            // 处理数组
            if (Array.isArray(obj)) {
                return obj.map(item => processLargeIntegers(item));
            }

            // 处理对象
            const result = {};
            for (const key in obj) {
                const value = obj[key];

                // 如果是id字段，并且是数字，检查是否需要转换为字符串
                if ((key === 'id' || key.endsWith('Id')) && typeof value === 'number') {
                    // 检查数字是否超过安全整数范围或接近边界
                    if (Math.abs(value) > 2 ** 52) {
                        result[key] = String(value);
                    } else {
                        result[key] = value;
                    }
                } else if (typeof value === 'object' && value !== null) {
                    // 递归处理嵌套对象
                    result[key] = processLargeIntegers(value);
                } else {
                    result[key] = value;
                }
            }
            return result;
        };

        // 转换响应数据格式为统一的 { code, data, message } 格式
        const data = processLargeIntegers(response.data);

        // 检查数据是否已经符合预期格式
        if (data && typeof data === 'object') {
            // 检查token是否过期或无效的错误码
            if (data.code === 401 || data.code === 403 ||
                (data.code !== 200 &&
                    (data.msg?.includes('令牌') ||
                        data.msg?.includes('token') ||
                        data.msg?.includes('登录') ||
                        data.msg?.includes('认证') ||
                        data.msg?.includes('未设置') ||
                        data.msg?.includes('过期')))) {

                // console.warn(`[${requestId}] 检测到token可能过期或无效: ${data.code}, ${data.msg}`);

                // 如果不是登录相关请求，则处理token过期
                if (!url.includes('/saas/auth/login') && !url.includes('/saas/auth/register') && !url.includes('/saas/auth/sms/login')) {
                    handleAuthError(requestId, data.code, response.config);

                    // 返回错误信息
                    if (getCurrentLanguage() === 'zh') {
                        return Promise.reject({
                            code: data.code,
                            message: data.msg || '登录已过期，请重新登录',
                            data: null
                        });
                    } else {
                        return Promise.reject({
                            code: data.code,
                            message: data.msg || 'Session expired, please log in again',
                            data: null
                        });
                    }
                }
            }

            // 处理业务错误码，包括余额不足等错误
            if (data.code !== 200) {
                // console.warn(`[${requestId}] 业务错误: ${data.code}, ${data.msg}`);

                // 判断是否显示错误消息弹窗
                if (!response.config._skipErrorMessage && data.msg) {
                    if (data.msg.includes('余额不足')) {
                        // 特殊处理余额不足的错误
                        // console.warn(`[${requestId}] 余额不足错误`);
                        if (getCurrentLanguage() === 'zh') {
                            ElMessage.error(data.msg);
                        } else {
                            ElMessage.error('Insufficient balance');
                        }
                    }
                }
            }

            if (data.code !== undefined) {
                // 如果响应已经包含code字段，直接返回
                // 确保有msg或message字段
                if (!data.msg && !data.message) {
                    data.msg = data.message || response.statusText || 'success';
                }
                return data;
            }

            // 对于原始数据，包装成统一格式
            return {
                code: response.status,
                data: data,
                msg: response.statusText || 'success'
            };
        }

        // 对于其他类型的响应，如文本或空响应，包装后返回
        return {
            code: response.status,
            data: data || response.data,
            msg: response.statusText || 'success'
        };
    },
    /**
     * 处理响应错误
     */
    error => {
        if (axios.isCancel(error)) {
            if (getCurrentLanguage() === 'zh') {
                return Promise.reject(new Error('请求被取消'));
            } else {
                return Promise.reject(new Error('Request canceled'));
            }
        }

        const requestId = error.config ? error.config.requestId : '未知';
        const method = error.config ? error.config.method.toUpperCase() : 'GET';
        const url = error.config ? error.config.url : '未知URL';

        // console.error(`[${requestId}] ${method}请求失败: ${url}`);
        // console.error(`[${requestId}] 错误详情:`, error);

        if (error.response) {
            // console.error(`[${requestId}] 响应状态: ${error.response.status}`);
            // console.error(`[${requestId}] 响应数据:`, error.response.data);

            // 对于认证相关错误，提供更详细的信息
            // if (url.includes('/saas/auth/')) {
            //     console.error(`[${requestId}] 认证请求失败细节:`, error.response.data);
            // }

            // 处理不同的HTTP状态码
            const status = error.response.status;

            if (status === 401 || status === 403) {
                // 认证相关错误，如果不是登录/注册请求，则可能需要重新登录
                if (!url.includes('/saas/auth/login') && !url.includes('/saas/auth/register') && !url.includes('/saas/auth/sms/login')) {
                    // 非登录/注册请求的认证错误
                    // console.warn(`[${requestId}] 认证失败，可能需要重新登录`);
                    handleAuthError(requestId, status, error.config);
                } else {
                    // 登录/注册请求的认证错误
                    // console.warn(`[${requestId}] 登录/注册认证错误:`, error.response.data);
                }
            }

            // 尝试从响应数据中获取详细错误信息
            let errorMessage = '请求失败';
            try {
                // 检查各种可能的错误消息字段
                if (error.response.data) {
                    if (typeof error.response.data === 'string') {
                        errorMessage = error.response.data;
                    } else if (error.response.data.message) {
                        errorMessage = error.response.data.message;
                    } else if (error.response.data.msg) {
                        errorMessage = error.response.data.msg;
                    } else if (error.response.data.error) {
                        errorMessage = error.response.data.error;
                    }
                }
            } catch (e) {
                // console.error(`[${requestId}] 解析错误消息失败:`, e);
            }

            // 如果不是由请求发起者处理错误，则显示错误消息提示
            if (!error.config || !error.config._skipErrorMessage) {
                try {
                    ElMessage.error(errorMessage);
                } catch (e) {
                    // console.error(`[${requestId}] 无法显示错误消息:`, e);
                }
            }

            // 将错误响应格式化为统一格式
            return Promise.reject({
                code: status,
                message: errorMessage,
                response: error.response,
                data: error.response.data
            });
        }

        // 网络错误或其他错误
        const errorMessage = error.message || '网络错误，请检查您的网络连接';

        // 如果不是由请求发起者处理错误，则显示错误消息提示
        if (!error.config || !error.config._skipErrorMessage) {
            try {
                if (getCurrentLanguage() === 'zh') {
                    ElMessage.error(errorMessage);
                } else {
                    ElMessage.error('Network error, please check your network connection');
                }
            } catch (e) {
                // console.error('无法显示错误消息:', e);
            }
        }

        return Promise.reject({
            code: error.code || 500,
            message: errorMessage,
            data: null
        });
    }
);

/**
 * 显示错误消息
 * @param {string} message 错误消息
 */
function showErrorMessage(message) {
    ElMessage.error(message);
}

// 同时使用命名导出和默认导出
export {request}
export default request; 